package com.ghck.server.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ghck.server.dao.TestCategoryDictMapper;
import com.ghck.server.dao.TestQuestionItemMapper;
import com.ghck.server.dao.TestQuestionMapper;
import com.ghck.server.model.TestCategoryDict;
import com.ghck.server.model.TestQuestionItem;
import com.ghck.server.model.query.TestCategoryDictQuery;
import com.ghck.server.model.response.TestCategoryDictRes;
import com.ghck.server.model.response.TestQuestionRes;
import com.ghck.server.service.TestCategoryDictService;
import com.ghck.server.utils.IntegerUtil;
import com.ghck.server.utils.RedisKeyUtil;

/**
 * 健康自测类型-支持管理平台配置  <br>
 * dict_test_category <br>
 * v1.0 2016-05-01
 */
 @Service
 @Transactional
 public class TestCategoryDictServiceImpl implements TestCategoryDictService {
	
	private static final Logger logger = LoggerFactory.getLogger(TestCategoryDictServiceImpl.class);
	
	@Autowired
	private TestCategoryDictMapper testCategoryDictMapper;
	
	@Autowired
	private TestQuestionMapper testQuestionMapper;
	
	@Autowired
	private TestQuestionItemMapper testQuestionItemMapper;
	
	@Autowired
	private RedisTemplate<String, Object> template;
	
	/**
 	*根据ID删除 健康自测类型-支持管理平台配置
 	*/
 	@Override
 	public Integer deleteTestCategoryDictById(Integer id){
 		return testCategoryDictMapper.deleteById(id);
 	}
 	
 	/**
 	*新增 健康自测类型-支持管理平台配置
 	*/
 	@Override
 	@Transactional
 	public Integer batchInsertTestCategoryDict(List<? extends TestCategoryDict> testCategoryDicts){
		Integer count = testCategoryDictMapper.batchInsert(testCategoryDicts);
		return count;
 	}
 	/**
 	*新增 健康自测类型-支持管理平台配置
 	*/
 	@Override
 	@Transactional
 	public Integer insertTestCategoryDict(TestCategoryDict domain){
		Integer id = testCategoryDictMapper.insert(domain);
		return id;
 	}

 	/**
 	*更新 健康自测类型-支持管理平台配置
 	*/
 	@Override
 	@Transactional
 	public Integer updateTestCategoryDict(TestCategoryDict domain){
		Integer count = testCategoryDictMapper.update(domain);
		return count;
 	}
 	
 	/**
 	*根据ID查询 健康自测类型-支持管理平台配置
 	*/
 	public TestCategoryDict findTestCategoryDictById(Integer id){
 		TestCategoryDict result = testCategoryDictMapper.findById(id);
 		if(result!=null){
 			result.dealWith();
 		}
 		return result;
 	}

	/**
 	*通过query 查询 健康自测类型-支持管理平台配置
 	*/
	public List<TestCategoryDict> findTestCategoryDictByQuery(TestCategoryDictQuery query){
		query.dealWith();
		List<TestCategoryDict> result = testCategoryDictMapper.findByQuery(query);
		if(CollectionUtils.isNotEmpty(result)) {
			for (TestCategoryDict testCategoryDict : result) {
				testCategoryDict.dealWith();
			}
		}
		return result;
	}	
	
	/**
 	*通过query count总条数
 	*/
 	public Integer countTestCategoryDictByQuery(TestCategoryDictQuery query){
 		query.dealWith();
 		Integer result = testCategoryDictMapper.countByQuery(query);
 		return result;
 	}
 	
 	/**
 	* 通过ids查询
 	*/
 	public List<TestCategoryDict> findTestCategoryDictByIds(List<Integer> ids){
 		List<TestCategoryDict> result = testCategoryDictMapper.findByIds(ids);
		if(CollectionUtils.isNotEmpty(result)) {
			for (TestCategoryDict testCategoryDict : result) {
				testCategoryDict.dealWith();
			}
		}
		return result;
 	}
 	
 	/**
 	*根据name查询 身体部位
 	*/
	public TestCategoryDict findByName(String name){
		TestCategoryDict result = testCategoryDictMapper.findByName(name);
 		if(result!=null){
 			result.dealWith();
 		}
 		return result;
	}
	
	/**
 	*获取所有字典 身体部位
 	*/
	public List<TestCategoryDictRes> findAll(){
		List<TestCategoryDictRes> result = testCategoryDictMapper.findAll();
		if(CollectionUtils.isNotEmpty(result)) {
			for (TestCategoryDict testCategoryDict : result) {
				testCategoryDict.dealWith();
			}
		}
		return result;
	}
	
	@Override
	public List<TestCategoryDict> findByParentId(Integer parentId,Integer start,Integer limit) {
		List<TestCategoryDict> result = testCategoryDictMapper.findByParentId(parentId, start, limit);
		if(CollectionUtils.isNotEmpty(result)) {
			for (TestCategoryDict testCategoryDict : result) {
				testCategoryDict.dealWith();
			}
		}
		return result;
	}
	
	/**
	 * 根据试卷ID查询试卷详情
	 * @param paperId
	 * @return 
	 */
	@Override
	public TestCategoryDictRes findPaperById(Integer paperId) {
		//通过id查询TestCategoryDictRes
		TestCategoryDictRes result = testCategoryDictMapper.findResById(paperId);
		if(result!=null){
			List<TestQuestionRes> questions = testQuestionMapper.findByCategoryId(paperId);
			if (CollectionUtils.isNotEmpty(questions)) {
				Map<Integer, TestQuestionRes> idMapTestQuestionRes = new HashMap<Integer, TestQuestionRes>();
				result.setTestQuestionResList(questions);
				List<Integer> questionIdList = new ArrayList<Integer>();
				for (TestQuestionRes testQuestionRes : questions) {
					idMapTestQuestionRes.put(testQuestionRes.getId(), testQuestionRes);
					questionIdList.add(testQuestionRes.getId());
				}
				List<TestQuestionItem> questionItems = testQuestionItemMapper.findByQuestionIds(questionIdList);
				if (CollectionUtils.isNotEmpty(questionItems)) {
					for (TestQuestionItem testQuestionItem : questionItems) {
						TestQuestionRes qRes =idMapTestQuestionRes.get(testQuestionItem.getParentId());
						if(qRes!=null){
							qRes.addTestQuestionItem(testQuestionItem);
						}
					}
				}
			}
			result.dealWith();
		}
		return result;
	}

	/**
	 * 根据试卷ID查询试卷详情
	 * @param paperId
	 * @return 
	 */
	@Override
	public TestCategoryDictRes findPaperByIdWithCahche(Integer paperId) {
		String key = RedisKeyUtil.paperHashKey();
		if(!template.hasKey(key)){
			syncInRedis(true);
		}
		HashOperations<String, String, TestCategoryDictRes> operations = template.opsForHash();
		String hashKey = RedisKeyUtil.domainIdKey(paperId);
		return operations.get(key, hashKey);
	}
	
	@Override
	public void syncSingletonRedis(Integer paperId) {
		String key = RedisKeyUtil.paperHashKey();
		String key2 = RedisKeyUtil.paperSampleHashKey();
		String key3 = RedisKeyUtil.parentIdMapPaperSampleChildren();
		if(!template.hasKey(key)){
			syncInRedis(true);
		}else{
			TestCategoryDictRes res = findPaperById(paperId);
			TestCategoryDictRes resSample = testCategoryDictMapper.findById(paperId);
			Integer parentId = res.getParentId();
			
			String hashKey = RedisKeyUtil.domainIdKey(paperId);
			String parentIdKey = RedisKeyUtil.domainIdKey(parentId);
			HashOperations<String, String, List<Integer>> hashOperations = template.opsForHash();
			if(res==null || res.getInUsed()==0){
				template.opsForHash().delete(key, hashKey);
				template.opsForHash().delete(key2, hashKey);
				if(hashOperations.hasKey(key3, parentIdKey)){
					List<Integer> list = hashOperations.get(key3, parentIdKey);
					if (CollectionUtils.isNotEmpty(list)) {
						Object findObject = null;
						for (Integer integer : list) {
							if(integer.intValue() == paperId){
								findObject = integer;
								break;
							}
						}
						if(findObject!=null){
							list.remove(findObject);
							hashOperations.put(key3, parentIdKey, list);
						}
					}
				}
			}else{
				template.opsForHash().put(key, hashKey, res);
				template.opsForHash().put(key2, hashKey,resSample);
				List<Integer> list =null;
				if(hashOperations.hasKey(key3, parentIdKey)){
					list = hashOperations.get(key3, parentIdKey);
					if (CollectionUtils.isNotEmpty(list)) {
						Object findObject = null;
						for (Integer integer : list) {
							if(integer.intValue() == paperId){
								findObject = integer;
								break;
							}
						}
						if(findObject==null){
							list.add(paperId);
							hashOperations.put(key3, parentIdKey, list);
						}
					}
				}else{
					list = new ArrayList<>();
					list.add(paperId);
					hashOperations.put(key3, parentIdKey, list);
				}
			}
		}
	}

	@Override
	public void syncInRedis(boolean force) {
		String key = RedisKeyUtil.paperHashKey();
		String key2 = RedisKeyUtil.paperSampleHashKey();
		String key3 = RedisKeyUtil.parentIdMapPaperSampleChildren();
		if(force || (!template.hasKey(key) )){
			template.delete(key);
			template.delete(key2);
			template.delete(key3);
			List<TestCategoryDictRes> paperList = testCategoryDictMapper.findAll();
			
			Map<String, TestCategoryDictRes> map = new HashMap<>();
			Map<String, TestCategoryDictRes> map2 = new HashMap<>();
			Map<String, List<Integer>> map3 = new HashMap<String, List<Integer>>();
			if (CollectionUtils.isNotEmpty(paperList)) {
				for (TestCategoryDictRes testCategoryDictRes : paperList) {
					if(IntegerUtil.isPositiveInteger(testCategoryDictRes.getParentId())){
						Integer paperId = testCategoryDictRes.getId();
						String hashKey = RedisKeyUtil.domainIdKey(paperId);
						map2.put(hashKey, testCategoryDictRes);
						
						Integer parentId = testCategoryDictRes.getParentId();
						String parentIdKey = RedisKeyUtil.domainIdKey(parentId);
						if(!map3.containsKey(hashKey)){
							map3.put(parentIdKey, new ArrayList<>());
						}
						map3.get(parentIdKey).add(paperId);
						
						testCategoryDictRes = findPaperById(paperId);
						map.put(hashKey, testCategoryDictRes);
					}
				}
			}
			if(!map.isEmpty()){
				template.opsForHash().putAll(key, map);
			}
			if(!map2.isEmpty()){
				template.opsForHash().putAll(key2, map2);
			}
			if(!map3.isEmpty()){
				template.opsForHash().putAll(key3, map3);
			}
		}
	}
}	